﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.ComponentModel;

namespace MillerApp.CommonLib.Utility
{
    public class ReflectionHelper
    {
        /// <summary>
        /// 属性集缓冲器
        /// </summary>
        private IDictionary<string, PropertyInfo> propertyCache;
        private IDictionary<Type, TypeConverter> converters;
 

        public ReflectionHelper()
        {
            this.propertyCache = new Dictionary<string, PropertyInfo>();
            this.converters = new Dictionary<Type, TypeConverter>(); 
        }

        public TypeConverter GetConverter(Type type)
        {
            if (this.converters.ContainsKey(type))
            {
                return this.converters[type];
            }
            return TypeDescriptor.GetConverter(type);
        }

        /// <summary>
        /// 获取对象特定属性的值
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="propertyNameString">对象属性字符串</param>
        /// <returns></returns>
        public object GetPropertyValue(object obj, string propertyNameString)
        {
            Type type =obj.GetType();
            PropertyInfo property = this.GetProperty(type, propertyNameString);
            if (property != null)
            {
                return property.GetValue(obj, null);
            }
            return null;
        }

        /// <summary>
        /// 设置对象特定属性的值
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyNameString"></param>
        /// <param name="propertyValue"></param>
        //public void SetPropertyValue(object obj, string propertyNameString, object propertyValue)
        //{

        //}


        public PropertyInfo GetProperty(Type type, string propertyName)
        {
            string key = type.FullName + "," + propertyName;
            PropertyInfo property = null;
            if (this.propertyCache.ContainsKey(key))
            {
                return this.propertyCache[key];
            }
            property = type.GetProperty(propertyName);
            this.propertyCache[key] = property;
            return property;
        }

        public void SetPropertyValue(object item, string propertyName, object propertyValue)
        {
            if (propertyValue == null || propertyValue == DBNull.Value)
            {
                return;
            }
            Type type = item.GetType();
            PropertyInfo property = this.GetProperty(type, propertyName);
            PropertyInfo propertySpecified = this.GetProperty(type, propertyName + "Specified");
            //以上属性是因为与其他语言接口定义中一般有这个，如果定义为False，即使是值类型也不会传送
            if (property == null)
            {
                return;
            }
            object convertObj = null;
            if (property.PropertyType == propertyValue.GetType())
            {
                convertObj = propertyValue;
            }
            else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal?))
            {
                convertObj = System.Convert.ToDecimal(propertyValue);
            }
            else
            {
                TypeConverter converter = this.GetConverter(property.PropertyType);
                if (converter.GetType() == typeof(StringConverter))
                {
                    convertObj = converter.ConvertToString(propertyValue);
                }
                else
                {
                    convertObj = converter.ConvertFrom(propertyValue);
                }
            }
            property.SetValue(item, convertObj, null);
            if (propertySpecified != null)
            {
                propertySpecified.SetValue(item, true, null);
            }
        }

    }
}
